﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Messaging;

namespace Songhay.Silverlight.BiggestBox
{
    using Songhay.Mvvm.Models;

    /// <summary>
    /// Represents the strategy of an asynchronous navigation operation.
    /// </summary>
    public class BiggestBoxNavigationContentLoader : NavigationContentLoader
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BiggestBoxNavigationContentLoader"/> class.
        /// </summary>
        public BiggestBoxNavigationContentLoader()
        {
            //TODO make these mappings configurable:
            this._uriMapper = new Dictionary<string, string>();
            this._uriMapper.Add("/index", "IndexPage");
            this._uriMapper.Add("/report/os", "ReportOSPage");
            this._uriMapper.Add("/sample/exception", "ExceptionPage");
            this._uriMapper.Add("/sample/packedxaml", "PackedXamlPage");
            this._uriMapper.Add("/sample/usercontrol", "UserControlsPage");

            #region messaging:

            Messenger.Default.Register<LightNotificationMessageAction<string>>(this,
            message =>
            {
                if(message.Source != LightMessageSource.ViewModel) return;
                if(message.UniqueId != "SamplesList") return;
                message.Execute(this._pageParameter);
            });

            Messenger.Default.Register<LightNotificationMessageAction<Page>>(this,
            message =>
            {
                if(message.Source != LightMessageSource.View) return;
                if(message.UniqueId != "ClientViewApplicationComposed") return;

                var uriFragment = GetUriFragment(message.Notification);
                var page = BiggestBoxCompositionHost.MefHost.GetPage(uriFragment);
                message.Execute(page);
            });

            #endregion
        }

        /// <summary>
        /// Begins asynchronous loading of the content for the specified target URI.
        /// </summary>
        /// <param name="targetUri">The URI to load content for.</param>
        /// <param name="currentUri">The URI that is currently loaded.</param>
        /// <param name="userCallback">The method to call when the content finishes loading.</param>
        /// <param name="asyncState">An object for storing custom state information.</param>
        /// <returns>
        /// An object that stores information about the asynchronous operation.
        /// </returns>
        public override IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
        {
            if((targetUri != null) && (currentUri != null))
            {
                var x1 = targetUri.OriginalString.Count(i => i == '/');
                var x2 = currentUri.OriginalString.Count(i => i == '/');
                if(x2 > x1) // Navigating away from sample ChildWindow.
                {
                    var message = new LightNotificationMessageAction<ChildWindow>("BeginLoad",
                    window =>
                    {
                        if(window == null) return;
                        window.Close();
                    });
                    Messenger.Default.Send(message);
                }
            }

            var result = new NavigationContentLoaderAsyncResult(asyncState);
            result.Result = this._page;
            userCallback(result);
            return result;
        }

        /// <summary>
        /// Gets a value that indicates whether the specified URI can be loaded.
        /// </summary>
        /// <param name="targetUri">The URI to test.</param>
        /// <param name="currentUri">The URI that is currently loaded.</param>
        /// <returns>
        /// true if the URI can be loaded; otherwise, false.
        /// </returns>
        public override bool CanLoad(Uri targetUri, Uri currentUri)
        {
            this._pageParameter = null;

            if(targetUri == null) return false;
            if(string.IsNullOrEmpty(targetUri.OriginalString)) return false;

            var uriFragment = GetUriFragment(targetUri.OriginalString);
            this._page = BiggestBoxCompositionHost.MefHost.GetPage(uriFragment);

            return (this._page != null);
        }

        string GetUriFragment(string originalString)
        {
            string uriFragment = null;

            var key = GetUriMapperKey(originalString, containsParameterInfo: false);
            if(this._uriMapper.ContainsKey(key)) uriFragment = this._uriMapper[key];
            else
            {
                key = this.GetUriMapperKey(key, containsParameterInfo: true);
                if(!string.IsNullOrEmpty(key) && this._uriMapper.ContainsKey(key)) uriFragment = this._uriMapper[key];
            }

            return uriFragment;
        }

        string GetUriMapperKey(string originalString, bool containsParameterInfo)
        {
            if(string.IsNullOrEmpty(originalString)) return null;

            if(!containsParameterInfo) return originalString.TrimEnd(new char[] { ' ', '/' });

            string key = null;

            var sArray = originalString.Split('/');
            if(!(sArray.Length > 3)) return null;

            key = originalString
                .Replace(sArray[3], string.Empty)
                .TrimEnd(new char[] { '/' });

            this._pageParameter = sArray[3];

            return key;
        }

        Page _page;
        string _pageParameter;
        Dictionary<string, string> _uriMapper;

    }
}
